from PyFlac.Carbon import CarbonUtils
from PyFlac.Carbon import CarbonJob
from PyFlac.Carbon import CarbonSocketLayer
import smtplib
import time
import datetime
# Import the email modules we'll need
from email.mime.text import MIMEText
import tclib
import shlex, subprocess, time
import os
import re

SRC_SMB_PATH = '\\\\10.221.173.151\\AudioInsert\\ffmbc_out\\'
DST_SMB_PATH = '\\\\10.221.173.231\\hd_audio_insert\\outbox'
GUID     = '{58E98FF9-9EF8-459E-AF2E-C7D07DD712F0}'
CARBON   = '10.221.173.31'
FFMBC_PATH_IN  = "/data/AudioInsert/ffmbc_in"
FFMBC_PATH_OUT = "/data/AudioInsert/ffmbc_out"
FFMBC_PATH_LOG = "/data/AudioInsert/ffmbc_log" 


SMTP = '10.221.173.10'
FROM = 'AudioInsert@fox.com'
TO   = 'flacbuenosairescoordinadores@fox.com'


# Mapeo de Audios:
# -map_audio_channel file:stream:channel[:outfile:stream]  set audio channel extraction on stream
ffmbc_map_options  = "-ac 8 -map_audio_channel 0:1:0:0:7 \
		            -map_audio_channel 0:2:0:0:8 \
                            -map_audio_channel 1:0:0:0:1 \
                            -map_audio_channel 2:0:0:0:2 \
                            -map_audio_channel 3:0:0:0:3 \
                            -map_audio_channel 4:0:0:0:4 \
                            -map_audio_channel 5:0:0:0:5 \
                            -map_audio_channel 6:0:0:0:6 -acodec pcm_s24le"

# Copia el formato de origen del video
ffmbc_vcodec       = "-vcodec copy"
#ffmbc_vcodec       = "-target xdcamhd422"


# Crea los nuevos audios (stream ) en 24bits
ffmbc_audio_output = "-acodec pcm_s24le -newaudio \
	              -acodec pcm_s24le -newaudio \
                      -acodec pcm_s24le -newaudio \
                      -acodec pcm_s24le -newaudio \
                      -acodec pcm_s24le -newaudio \
                      -acodec pcm_s24le -newaudio \
                      -acodec pcm_s24le -newaudio"


#Ubicacion del ejecutable
ffmbc_bin          = "/usr/local/bin/ffmbc" 

def test_ffmbc_bin():
	""" Testea la existencia del ejecutable ffmbc declarado en la variable ffmbc_bin"""
	""" Retorna: True en caso de exito, de lo contrario False """
	if (os.path.isfile(ffmbc_bin)):
		return True

	return False		


# Send the message via our own SMTP server, but don't include the
# envelope header.

def SendReport(files_ok = [], files_errors = []):
        today = datetime.date.today()

        subject = "REPORTE DE INSERSION DE AUDIOS " + today.strftime('%d, %h %Y')

        msg = MIMEText(subject)
        msg['Subject'] = subject
        msg['From'] = FROM
        msg['To']   = TO


        message = subject
        message = message + "\n\n"
        message = message + "FILES OK (Listos para Importar):\n"

        for ok in files_ok:
                message = message + ok + "\n"

        message = message + "\n\n"
        message = message + "FILES CON ERRORES:\n"

        for err in files_errors:
                message = message + err['filename'] + " -> Error: " + err['error'] + "\n"


        msg = MIMEText(message)
        msg['Subject'] = subject
        msg['From'] = FROM
        msg['To']   = TO


        s = smtplib.SMTP(SMTP)
        s.sendmail(FROM, [TO], msg.as_string())
        s.quit()



class mediaPackage(object):
	def __init__ (self):
		self.__video         = None
		self.__left          = None
		self.__right         = None
		self.__center        = None
		self.__lfe           = None
		self.__leftsurround  = None
		self.__rightsurround = None
		self.__ffmbc_inputs  = None
		self.__minduration   = None
		self.__ffmbc_errors  = None
		self.__rhozet_errors = None
		self.__dst_path	     = None
		self.__dst_ffmbc     = None


	def SetDestination(self, path, filename):
		self.__dst_path  = path
		self.__dst_ffmbc = filename


	def GetDestinationFilename(self):
		if self.__dst_path and self.__dst_ffmbc:
			return self.__dst_path + '/' + self.__dst_ffmbc


	def TestDuration(self,file):
		ms = tclib.GetMediaDuration(file)
		print "MS: " + ms
		print "FILE: " + file
		if self.__minduration == None:
			self.__minduration = ms
		else:
			if ms < self.__minduration:
				self.__minduration = ms

	def GetMinMediaDuration(self):
		return self.__minduration

	def video(self, v):
		self.__video = v
		self.TestDuration(v)
	
	def left(self, l):
		self.__left  = l
		self.TestDuration(l)

	def right(self, r):
		self.__right = r
		self.TestDuration(r)

	def center(self, c):
		self.__center = c
		self.TestDuration(c)

	def lfe(self, lf):
		self.__lfe = lf
		self.TestDuration(lf)

	def leftsurround(self, ls):
		self.__leftsurround  = ls
		self.TestDuration(ls)

	def rightsurround(self, rs):
		self.__rightsurround = rs
		self.TestDuration(rs)

	def packageComplete(self):
		""" Testea la existencia de todos los archivos que forman el paquete """	
		if ( self.__video != None  and 
		     self.__left != None   and 
                     self.__right != None  and 
                     self.__center != None and 
                     self.__lfe != None    and 
                     self.__leftsurround  != None and 
                     self.__rightsurround != None):
			# Setea la variable __ffmbc_inputs con los archivos correspondientes
			self.__ffmbc_inputs = ' -i ' + self.__video  + \
                                              ' -i ' + self.__left   + \
                                              ' -i ' + self.__right  + \
                                              ' -i ' + self.__center + \
                                              ' -i ' + self.__lfe    + \
                                              ' -i ' + self.__leftsurround + ' -i ' + self.__rightsurround
			return True
		else:
			return False




	def ffmbcJoinAudio(self, dstlog = None):
		if self.packageComplete():
			dstfile = self.GetDestinationFilename()
		# Si estan todos los archivos para insertar
			if (dstfile != None and dstlog != None):
				if test_ffmbc_bin():
				#	starttc = tclib.GetStartTC(self.__video)
				#	if starttc == None:
				#		return (-1, "ERROR: Imposible leer el timecode")

					# Con la existencia del binario genera el string con los comandos necesarios para ffmbc	
					minduration    = self.GetMinMediaDuration()
					print "MIN DUR: " + minduration
					mindurationStr = tclib.msToString(minduration)
					ffmbc_cmd = ffmbc_bin + ' ' +\
                                                    self.__ffmbc_inputs + ' ' + \
                                                    ffmbc_map_options   + ' ' + \
						    ' -timecode '       + '00:58:20;00' +  ' ' +\
                                                    ffmbc_vcodec        + ' ' + \
                                                    '-t ' + mindurationStr + ' ' + dstfile + ' ' + ffmbc_audio_output
					try:
						file = open(dstlog, "w")
					except:
						return (-1, "ERROR: Imposible abrir el archivo " + dstlog )
					
					# Crea el proceso y lo executa	
					print ffmbc_cmd
					args = shlex.split(ffmbc_cmd)
					p = subprocess.Popen(args, stdout = file, stderr = file)
					return (os.waitpid(p.pid, 0)[1], "FFMBC")
				else:
					return (-1, "ERROR: No existe el ejecutable ffmbc en " + ffmbc )
		else:
			return (-1, "ERROR: El paquete esta incompleto")



	def CarbonTranscode(self,basename):
		filename = self.__dst_ffmbc
        	carbon = CarbonSocketLayer.CarbonSocketLayer(CARBON)
        	jobXml = CarbonUtils.CreateCarbonXMLJob(SRC_SMB_PATH, filename, [], [{'d_guid': GUID, 'd_basename': basename, 'd_path': DST_SMB_PATH}])
	
       	 	print jobXml

        	job = CarbonJob.CarbonJob(carbon, jobXml)
        	if job.Start():
                	status = job.GetStatus(True)
                	while status == "STARTED" or status == "QUEUED":
                        	time.sleep(20)
                        	status = job.GetStatus(True)

                	if status == "COMPLETED":
                        	return (True, basename + ".mxf", status)
                	else:
                        	return (False, job.GetErrors , status)
        	else:
                	return (False, job.GetErrors, "ERROR")
	
	def UnlinkMedia(self):
		if self.packageComplete():
			os.unlink(self.__video)
                     	os.unlink(self.__left)
                     	os.unlink(self.__right)
                     	os.unlink(self.__center)
                     	os.unlink(self.__lfe)
                     	os.unlink(self.__leftsurround)
                     	os.unlink(self.__rightsurround)	


def GetPattern(str = ""):
        if str != "":
                wlist = str.split("_")
                if len(wlist) > 3:
                        return (wlist[0] + "_" + wlist[1] + "_" + wlist[2] + "_")

        return None


def GetFileByPattern (pattern = "", fileList = []):

        for file in fileList:
                if re.match(pattern, file):
                        return file

        return None



def ScanPath (path = None, dstpath = None, procpath = None, logs = None):

        video  = []
        lfe    = []
        right  = []
        left   = []
        center = []
        rightsurround = []
        leftsurround  = []

	proc_finish = []
	proc_errors = []


	# Lista el path en busca de los diferentes tipos de archivos
        # y los clasifica en distintas listas	

        file_list = os.listdir(path)
        for file in file_list:
		if re.search("#", file):
			continue

                if file.endswith(".mxf"):
                        video.append(file)
                else:
                        if file.endswith(".wav"):
                                if re.search("_LFE_", file) != None:
                                        lfe.append(file)

                                if re.search("_Center_", file) != None:
                                        center.append(file)

                                if re.search("_LeftSurround_", file) != None:
                                        leftsurround.append(file)

                                if re.search("_RightSurround_", file) != None:
                                        rightsurround.append(file)

                                if re.search("_Left_", file) != None:
                                        left.append(file)

                                if re.search("_Right_", file) != None:
                                        right.append(file)


	for v in video:
		media = mediaPackage()
		# Por cada archivo de video encontrado
		# Extrae el patron AA_BB_CC
		pattern = GetPattern(v)
		if pattern != None:
			media.video(path + "/" + v)
			
			# Search lfe
			audio = GetFileByPattern(pattern, lfe)
			if audio != None:
				media.lfe(path + "/" + audio)
			# Search Center
			audio = GetFileByPattern(pattern, center)
			if audio != None:
				media.center(path + "/" + audio)
			# Search left
			audio = GetFileByPattern(pattern, left)
			if audio != None:
				media.left(path + "/" + audio)
			# Search Right
			audio = GetFileByPattern(pattern, right)
			if audio != None:
				media.right(path + "/" + audio)
			# Search rightsurround
			audio = GetFileByPattern(pattern, rightsurround)
			if audio != None:	 
				media.rightsurround(path + "/" + audio)
			# Seach leftsurround
			audio = GetFileByPattern(pattern, leftsurround)
			if audio != None:
				media.leftsurround(path + "/" + audio)


		if media.packageComplete():
			dstlog  = logs    + "/" + pattern +  ".log"
		
			media.SetDestination(dstpath, pattern + "Audios-5_1.mxf")

			# Si ya existe el file de destino hay que borrarlo

			if (os.path.isfile(media.GetDestinationFilename())):
				os.remove(media.GetDestinationFilename())
	
			ret, msg = media.ffmbcJoinAudio(dstlog)
			if ( ret == 0 ):
			# Si la insersion de Audios termino Correctamente
			# 1- Manadar a transcodificar a Rhozet por la API
				ret, msg, status = media.CarbonTranscode(pattern + "5_1_RHOZET")
			
				if ret:
				# Si la trancodificacion de Rhozet Termino correctamente
				# 1 - Borrar el file generado por FFMBC
				# 2 - Agrega el file como terminado correcto para el reporte

					os.unlink(media.GetDestinationFilename())
					proc_finish.append(pattern + "5_1_RHOZET.mxf")
					media.UnlinkMedia()
				else:
					print "Carbon Fallo"
					proc_errors.append({ 'filename' : pattern + "5_1_RHOZET.mxf", 'error' : "Carbon Error"} )		
				
			else:
				print "FFMBC Fallo"
				proc_errors.append({ 'filename': pattern  + "Audios-5_1.mxf", 'error' : "FFMBC - " + msg })
		else:
			print "Paquete Inconmpleto"
			proc_errors.append({'filename': v , 'error' : "Paquete Incompleto" } )
	
	SendReport(proc_finish, proc_errors)
	

ScanPath(FFMBC_PATH_IN, FFMBC_PATH_OUT, "", FFMBC_PATH_LOG)
